package com.xzzz.backend.bsms.server.base.middleware;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.xzzz.backend.bsms.server.base.middleware.pojo.MiddlewareInfoRes;
import com.xzzz.common.base.pojo.R;
import com.xzzz.common.base.util.json.JsonUtil;
import com.xzzz.common.base.util.okhttp.HttpUtil;
import com.xzzz.irda.guardcat.client.alert.AlertClientSender;
import com.xzzz.irda.guardcat.core.pojo.Alert;
import com.xzzz.irda.tracker.core.adapter.aspect.TrackerStart;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;

/**
 * 中间件接口
 */
@Slf4j
@RestController
@RequestMapping("/middleware")
public class MiddlewareController {

    Map<String, MiddlewareInfoRes> cache = new HashMap<>();

    Map<String, Integer> errCountCache = new HashMap<>();

    private static final int ALERT_COUNT = 3;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    @Qualifier("taskExecutor")
    private Executor executor;

    /**
     * 获取中间状态
     *
     * @return 中间件状态
     */
    @GetMapping
    public R<Collection<MiddlewareInfoRes>> getAll() {
        return R.ok(cache.values());
    }


    @Scheduled(cron = "0 0/5 * * * ?")
    @TrackerStart
    public void refresh() {
//        executor.execute(this::redis);
//        executor.execute(this::logstash);
//        executor.execute(this::filebeat);
//        executor.execute(this::elasticsearch);
    }

    private void sendError(MiddlewareInfoRes middleware, String errMsg) {
        int errCount = errCountCache.getOrDefault(middleware.getType(), 0);
        errCount = errCount + 1;

        log.warn("中间件异常通知 [{}] 发生异常, 异常次数: [{}]", middleware.getDesc(), errCount);

        if (errCount >= ALERT_COUNT) {
            Alert alert = Alert.build(
                    "中间件异常通知",
                    String.format("%s：%s", middleware.getDesc(), errMsg),
                    true);
            AlertClientSender.send(alert, true);
            clearError(middleware);
        } else {
            errCountCache.put(middleware.getType(), errCount);
        }
    }

    private void clearError(MiddlewareInfoRes middleware) {
        errCountCache.put(middleware.getType(), 0);
    }

    /**
     * redis 获取 Redis 信息
     */
    private void redis() {
        log.info("刷新中间件信息 [Redis]");
        MiddlewareInfoRes redis = MiddlewareInfoRes.buildNone("Redis", "localhost:6379");
        redis.setDesc("本地Redis");
        redis.setName("Redis");
        redis.setNodeTotal(1);
        String errMsg = null;

        try {
            Map<String, String> map = new HashMap(redisTemplate.getRequiredConnectionFactory().getConnection().info());
            if (MapUtil.isNotEmpty(map)) {
                redis.setVersion(map.get("redis_version"));
                redis.setNodeSuccess(1);
                redis.setNodeFailure(0);
            } else {
                redis.setNodeSuccess(0);
                redis.setNodeFailure(1);
                errMsg = "未查询到 REDIS INFO 信息";
            }
        } catch (Exception e) {
            redis.setNodeSuccess(0);
            redis.setNodeFailure(1);
            errMsg = e.getMessage();
        }

        if (StrUtil.isNotBlank(errMsg)) {
            sendError(redis, errMsg);
        } else {
            clearError(redis);
        }

        cache.put(redis.getType(), redis);

    }


    private void elasticsearch() {
        log.info("刷新中间件信息 [ElasticSearch]");
        MiddlewareInfoRes es = MiddlewareInfoRes.buildNone("ElasticSearch", "http://127.0.0.1:9200");
        es.setDesc("腾讯云S5:ElasticSearch");
        String errMsg = null;

        try {
            String body = HttpUtil.get(es.getUrl() + "/_cluster/stats");
            if (StrUtil.isNotBlank(body)) {
                JsonNode jsonNode = JsonUtil.toJsonNode(body);
                es.setName(jsonNode.get("cluster_name").asText());
                es.setVersion(jsonNode.get("nodes").get("versions").get(0).asText());
                // 节点个数
                es.setNodeTotal(jsonNode.get("_nodes").get("total").asInt());
                es.setNodeSuccess(jsonNode.get("_nodes").get("successful").asInt());
                es.setNodeFailure(jsonNode.get("_nodes").get("failed").asInt());
            } else {
                errMsg = "未获取到 ElasticSearch 信息";
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("{}无法连接: {}", es.getDesc(), e.getMessage());
            errMsg = e.getMessage();
        }

        if (StrUtil.isNotBlank(errMsg)) {
            sendError(es, errMsg);
        } else {
            clearError(es);
        }

        cache.put(es.getType(), es);
    }

    private void logstash() {
        log.info("刷新中间件信息 [LogStash]");
        MiddlewareInfoRes ls = MiddlewareInfoRes.buildNone("LogStash", "http://127.0.0.1:9600");
        ls.setDesc("腾讯云S5:LogStash");
        ls.setNodeTotal(1);
        String errMsg = null;

        try {
            String body = HttpUtil.get(ls.getUrl());
            if (StrUtil.isNotBlank(body)) {
                JsonNode jsonNode = JsonUtil.toJsonNode(body);
                ls.setName(jsonNode.get("name").asText());
                ls.setVersion(jsonNode.get("version").asText());
                ls.setNodeSuccess(1);
                ls.setNodeFailure(0);
            } else {
                ls.setNodeSuccess(0);
                ls.setNodeFailure(1);
                errMsg = "未获取到 LOGSTASH 信息";
            }
        } catch (Exception e) {
            log.error("{}无法连接: {}", ls.getDesc(), e.getMessage());
            ls.setNodeSuccess(0);
            ls.setNodeFailure(1);
            errMsg = e.getMessage();
        }

        if (StrUtil.isNotBlank(errMsg)) {
            sendError(ls, errMsg);
        } else {
            clearError(ls);
        }

        cache.put(ls.getType(), ls);
    }


    private void filebeat() {
        log.info("刷新中间件信息 [FileBeat]");
        MiddlewareInfoRes fb = MiddlewareInfoRes.buildNone("FileBeat", "http://111.229.200.229:5066");
        fb.setDesc("腾讯云标准型S2:FileBeat");
        fb.setNodeTotal(1);
        String errMsg = null;

        try {
            String body = HttpUtil.get(fb.getUrl());
            if (StrUtil.isNotBlank(body)) {
                JsonNode jsonNode = JsonUtil.toJsonNode(body);
                fb.setName(jsonNode.get("name").asText());
                fb.setVersion(jsonNode.get("version").asText());
                fb.setNodeSuccess(1);
                fb.setNodeFailure(0);
            } else {
                fb.setNodeSuccess(0);
                fb.setNodeFailure(1);
                errMsg = "未获取到 FileBeat 信息";
            }
        } catch (Exception e) {
            log.error("{}无法连接: {}", fb.getDesc(), e.getMessage());
            errMsg = e.getMessage();
        }

        if (StrUtil.isNotBlank(errMsg)) {
            sendError(fb, errMsg);
        } else {
            clearError(fb);
        }

        cache.put(fb.getType(), fb);
    }


}
